import {
	ref,
	reactive,
	computed,
	toRaw,
	isReactive,
	isRef,
	type Ref
} from "vue";
import {
	getProperty,
	timeFormat,
	isObj
} from "@/common/utils";
import {
	REQUEST_SUCCESS_CODE,
	DEFAULT_RESPONSE_KEY,
	DEFAULT_TOTAL_KEY
} from '@/env'
import type { ResponseData } from "@/common/request/type";

type PageLoad = (data: {
	loadList: Record<string, any>[],
	newList: any[],
	nowTotal: number,
	timeKey: string,
	format: string,
	pageNo?: number,
	limit?: number
}) => { pageNo: number,newTotal:number }

const pageLoad: PageLoad = ({
	loadList,
	newList,
	nowTotal,
	timeKey,
	format,
	pageNo = 1,
	limit = 20
}) => {
	// 加载内容是否为空
	if (newList.length !== 0) {
		// 判断是否为第一次加载
		if (nowTotal === 0) {
			// 判断是否有残留数据
			if (loadList.length !== 0) {
				loadList.splice(0, loadList.length);
			}
		}
		newList.forEach(item => {
			let date = timeFormat(getProperty(item, timeKey) as string, format)
			let index = loadList.findIndex(items => items.date === date)
			let data = index > -1 ? loadList[index] : {
				date,
				list: []
			}
			data.list.push(item)
			if (index > -1) {
				loadList.splice(index, 1, data)
			} else {
				loadList.push(data)
			}
		})
		// 加载数据是否够一页
		if (newList.length == limit) {
			pageNo++;
		}
		nowTotal += newList.length
	}
	return {
		pageNo,
		newTotal: nowTotal
	};
}

type option = {
	responseKey?: string;
	responseInterception?: (res: unknown) => void;
	params?: Record<string, any> | Ref<Record<string, any>>
	totalKey?: string,
	timeKey?: string,
	format?: string
};

type QueryPageParams<T> = {
	api: (data: any) => Promise<ResponseData<T | { list: T }>>;
	option?: option;
	pageSize?: number;
}

export function useQueryTimePage<T>({
	api,
	option,
	pageSize = 20,
}: QueryPageParams<T>) {
	type List = Array<{
		date: string,
		list: Array<T>
	}>
	//定义分页所需参数，
	const showLoad = ref(false);
	const list = reactive<List>([]);
	const requestQueue: Array<() => Promise<void>> = [];
	let isRefresh = false;
	let total = 0;
	let page = 1,
		isGet = true;
	const allRequest = async () => {
		let arr = [...requestQueue];
		for (let index in arr) {
			await arr[index]();
			requestQueue.splice(Number(index), 1);
		}
	};
	const handleQueryPage = async (params?: Record<string, any>) => {
		if (showLoad.value) {
			// 缓存请求队列，防止上个请求未执行完，导致page不正确
			requestQueue.push(handleQueryPage);
			return;
		}
		if (isGet) {
			showLoad.value = true;
			let data = {
				pageNum: page,
				pageSize: pageSize,
			};
			if (option?.params) {
				if (isRef(option.params)&&isObj(option.params.value)) {
					data = {
						...data,
						...option.params.value
					};
				} else {
					data = {
						...data,
						...option.params
					};
				}

			}
			if (params) {
				if (isReactive(params)) {
					data = {
						...data,
						...toRaw(params)
					};
				} else {
					data = {
						...data,
						...params
					};
				}
			}
			try {
				const res = await api(data)
				option?.responseInterception?.(res);
				if (REQUEST_SUCCESS_CODE.includes(res.code)) {
					if (isRefresh) {
						// 把重置列表的操作放到请求中，可以防止重置列表时，在接口请求完成前，页面出现短暂的无数据现象
						list.splice(0, list.length);
						isRefresh = false
					}
					let {
						pageNo,
						newTotal
					} = pageLoad({
						loadList: list,
						newList: getProperty(res, option?.responseKey || DEFAULT_RESPONSE_KEY) as any[],
						nowTotal: total,
						pageNo: page,
						limit:pageSize,
						timeKey: option?.timeKey || "createTime",
						format: option?.format || "yyyy-mm"
					});
					page = pageNo;
					total = newTotal;
					showLoad.value = false;
					if (total == getProperty(res, option?.totalKey ||DEFAULT_TOTAL_KEY)) {
						isGet = false;
					}
				}

			} catch (e) {
				await allRequest();
			}
		}
	};
	const handleRefresh = async (params?: Record<string, any>) => {
		isGet = true;
		page = 1;
		isRefresh = true;
		total = 0
		showLoad.value = false;
		requestQueue.splice(0, requestQueue.length);
		await handleQueryPage(params);
	};
	const isEmpty = computed(() => list.length === 0)
	return {
		showLoad,
		list,
		isEmpty,
		handleQueryPage,
		handleRefresh,
	};
}
